namespace CSharpKit.Numerics;

using System;
using System.Linq;
using System.Collections.Generic;

/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
public class NDArray<T> where T : struct, IComparable, IFormattable, IConvertible
{
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="shape"></param>
    public NDArray(params int[] shape)
    {
        if (shape == null || shape.Length == 0)
            throw new ArgumentException("Shape must have at least one dimension");

        _shape = (int[])shape.Clone();
        _strides = CalculateStrides(shape);
        _data = new T[CalculateTotalLength(shape)];
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="data"></param>
    /// <param name="shape"></param>
    /// <returns></returns>
    public NDArray(T[] data, params int[] shape) : this(shape)
    {
        if (data.Length != _data.Length)
            throw new ArgumentException("Data length doesn't match shape");

        Array.Copy(data, _data, data.Length);
    }

    private T[] _data;      // 数据
    private int[] _shape;   // 形状
    private int[] _strides; // Strides

    // 公共属性
    /// <summary>
    /// 形状
    /// </summary>
    /// <returns></returns>
    public int[] Shape => (int[])_shape.Clone();
    /// <summary>
    /// 秩
    /// </summary>
    public int Rank => _shape.Length;
    /// <summary>
    /// 长度
    /// </summary>
    public int Length => _data.Length;

    /// <summary>
    /// 索引器
    /// </summary>
    /// <value></value>
    public T this[params int[] indices]
    {
        get => _data[CalculateFlatIndex(indices)];
        set => _data[CalculateFlatIndex(indices)] = value;
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="shape"></param>
    /// <returns></returns>
    private int[] CalculateStrides(int[] shape)
    {
        var strides = new int[shape.Length];
        strides[strides.Length - 1] = 1;

        for (int i = strides.Length - 2; i >= 0; i--)
        {
            strides[i] = strides[i + 1] * shape[i + 1];
        }

        return strides;
    }

    private int CalculateTotalLength(int[] shape)
    {
        int total = 1;
        foreach (var dim in shape) total *= dim;
        return total;
    }

    private int CalculateFlatIndex(params int[] indices)
    {
        if (indices.Length != _shape.Length)
            throw new ArgumentException("Indices count must match dimensions");

        int index = 0;
        for (int i = 0; i < indices.Length; i++)
        {
            if (indices[i] >= _shape[i])
                throw new IndexOutOfRangeException();

            index += indices[i] * _strides[i];
        }

        return index;
    }

    // 基本操作
    /// <summary>
    /// 
    /// </summary>
    /// <param name="newShape"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException"></exception>
    public NDArray<T> Reshape(params int[] newShape)
    {
        if (CalculateTotalLength(newShape) != _data.Length)
            throw new ArgumentException("Total size must remain the same");

        var result = new NDArray<T>(newShape);
        Array.Copy(_data, result._data, _data.Length);
        return result;
    }

    /// <summary>
    /// 转置
    /// </summary>
    /// <returns></returns>
    public NDArray<T> Transpose()
    {
        var newShape = _shape.Reverse().ToArray();
        var result = new NDArray<T>(newShape);

        // 实现转置逻辑...
        // 这里需要更复杂的索引计算

        return result;
    }

    /// <summary>
    /// 数学运算 (需要动态编译或接口约束)
    /// </summary>
    /// <param name="other"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException"></exception>
    public NDArray<T> Add(NDArray<T> other)
    {
        if (!_shape.SequenceEqual(other._shape))
            throw new ArgumentException("Shapes must match");

        var result = new NDArray<T>(_shape);

        for (int i = 0; i < _data.Length; i++)
        {
            // 动态加法，实际项目中可以使用表达式树或泛型数学
            result._data[i] = (dynamic)_data[i] + (dynamic)other._data[i];
        }

        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="slices"></param>
    /// <returns></returns>
    public NDArray<T> Slice(params (int? start, int? end, int? step)[] slices)
    {
        // 实现切片逻辑...
        return null;
    }

    /// <summary>
    /// 工厂方法
    /// </summary>
    /// <param name="shape"></param>
    /// <returns></returns>
    public static NDArray<T> Zeros(params int[] shape)
    {
        var result = new NDArray<T>(shape);
        Array.Fill(result._data, default(T));
        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="shape"></param>
    /// <returns></returns>
    public static NDArray<T> Ones(params int[] shape)
    {
        var result = new NDArray<T>(shape);
        // 需要处理各种T类型的1值
        if (typeof(T) == typeof(int)) Array.Fill(result._data, (T)(object)1);
        else if (typeof(T) == typeof(double)) Array.Fill(result._data, (T)(object)1.0);
        // 其他类型处理...
        return result;
    }

    /// <summary>
    /// 转换方法
    /// </summary>
    /// <returns></returns>
    public T[] ToFlatArray() => (T[])_data.Clone();

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        // 实现多维数组的格式化输出...
        return "";
    }
}